// Copyright (C) ZHENG Zhong <heavyzheng nospam-at gmail D0T com>
//
// $Id: duration_test.cpp 228 2008-09-15 13:35:23Z heavyzheng $
//

#include <zzheng/quant/dates/quant_dates_test_cases.hpp>
#include <zzheng/quant/dates.hpp>
#include <zzheng/test_logging.hpp>

#include <boost/test/unit_test.hpp>
#include <string>

namespace zzheng {
namespace test {

    namespace {

        void test_duration_default_ctor() {
            info("Running test case: test_duration_default_ctor");
            quant::duration d;
            BOOST_CHECK_EQUAL(d.count(), 0);
            BOOST_CHECK_EQUAL(d.unit(), quant::duration::month);
        }

        void test_swap_durations() {
            info("Running test case: test_swap_durations");
            const int COUNT_1 = +100;
            const int COUNT_2 = -200;
            const quant::duration::unit_type UNIT_1 = quant::duration::day;
            const quant::duration::unit_type UNIT_2 = quant::duration::month;
            quant::duration d1(COUNT_1, UNIT_1);
            quant::duration d2(COUNT_2, UNIT_2);
            BOOST_CHECK_NO_THROW(d1.swap(d2));
            BOOST_CHECK_EQUAL(d1.count(), COUNT_2);
            BOOST_CHECK_EQUAL(d1.unit() , UNIT_2 );
            BOOST_CHECK_EQUAL(d2.count(), COUNT_1);
            BOOST_CHECK_EQUAL(d2.unit() , UNIT_1 );
        }

        void test_parse_string_to_duration() {
            info("Running test case: test_parse_string_to_duration");
            BOOST_CHECK_EQUAL(quant::parse_duration("  3d  "), quant::make_days(3));
            BOOST_CHECK_EQUAL(quant::parse_duration("   24D"), quant::make_days(24));
            BOOST_CHECK_EQUAL(quant::parse_duration("365d  "), quant::make_days(365));
            BOOST_CHECK_EQUAL(quant::parse_duration(" 56w  "), quant::make_weeks(56));
            BOOST_CHECK_EQUAL(quant::parse_duration(" 1024W"), quant::make_weeks(1024));
            BOOST_CHECK_EQUAL(quant::parse_duration("12345w"), quant::make_weeks(12345));
            BOOST_CHECK_EQUAL(quant::parse_duration("12m   "), quant::make_months(12));
            BOOST_CHECK_EQUAL(quant::parse_duration(" 240M "), quant::make_months(240));
            BOOST_CHECK_EQUAL(quant::parse_duration("12345m"), quant::make_months(12345));
            BOOST_CHECK_EQUAL(quant::parse_duration(" 200y "), quant::make_years(200));
            BOOST_CHECK_EQUAL(quant::parse_duration(" 1979Y"), quant::make_years(1979));
            BOOST_CHECK_EQUAL(quant::parse_duration("12345y"), quant::make_years(12345));
        }

        void test_parse_signed_string_to_duration() {
            info("Running test case: test_parse_signed_string_to_duration");
            BOOST_CHECK_EQUAL(quant::parse_duration("  +3d  "), quant::make_days(3));
            BOOST_CHECK_EQUAL(quant::parse_duration("   -24D"), quant::make_days(-24));
            BOOST_CHECK_EQUAL(quant::parse_duration("-365d  "), quant::make_days(-365));
            BOOST_CHECK_EQUAL(quant::parse_duration(" +56w  "), quant::make_weeks(+56));
            BOOST_CHECK_EQUAL(quant::parse_duration(" -1024W"), quant::make_weeks(-1024));
            BOOST_CHECK_EQUAL(quant::parse_duration("-12345w"), quant::make_weeks(-12345));
            BOOST_CHECK_EQUAL(quant::parse_duration("+12m   "), quant::make_months(+12));
            BOOST_CHECK_EQUAL(quant::parse_duration(" -240M "), quant::make_months(-240));
            BOOST_CHECK_EQUAL(quant::parse_duration("-12345m"), quant::make_months(-12345));
            BOOST_CHECK_EQUAL(quant::parse_duration(" +200y "), quant::make_years(+200));
            BOOST_CHECK_EQUAL(quant::parse_duration(" -1979Y"), quant::make_years(-1979));
            BOOST_CHECK_EQUAL(quant::parse_duration("-12345y"), quant::make_years(-12345));
        }

        void test_parse_invalid_string_to_duration() {
            info("Running test case: test_parse_invalid_string_to_duration");
            BOOST_CHECK_THROW( quant::parse_duration(""),      quant::date_error );
            BOOST_CHECK_THROW( quant::parse_duration(" "),     quant::date_error );
            BOOST_CHECK_THROW( quant::parse_duration("+12"),   quant::date_error );
            BOOST_CHECK_THROW( quant::parse_duration("-12"),   quant::date_error );
            BOOST_CHECK_THROW( quant::parse_duration("3 D"),   quant::date_error );
            BOOST_CHECK_THROW( quant::parse_duration("+3 W"),  quant::date_error );
            BOOST_CHECK_THROW( quant::parse_duration("+ 3M"),  quant::date_error );
            BOOST_CHECK_THROW( quant::parse_duration("+12Md"), quant::date_error );
            BOOST_CHECK_THROW( quant::parse_duration("M"),     quant::date_error );
            BOOST_CHECK_THROW( quant::parse_duration("M12"),   quant::date_error );
            BOOST_CHECK_THROW( quant::parse_duration("M12m"),  quant::date_error );
            BOOST_CHECK_THROW( quant::parse_duration("12mD"),  quant::date_error );
            BOOST_CHECK_THROW( quant::parse_duration("12mm"),  quant::date_error );
            BOOST_CHECK_THROW( quant::parse_duration("12X"),   quant::date_error );
            BOOST_CHECK_THROW( quant::parse_duration("12"),    quant::date_error );
        }

        void test_add_duration() {

            info("Running test case: test_add_duration");

            quant::date d1 = quant::add_duration( quant::date(2000, 2, 20),
                                                  quant::make_days(10),
                                                  true );
            BOOST_CHECK_EQUAL(d1, quant::date(2000, 3, 1));

            quant::date d2 = quant::add_duration( quant::date(2001, 2, 20),
                                                  quant::make_days(10),
                                                  true );
            BOOST_CHECK_EQUAL(d2, quant::date(2001, 3, 2));

            quant::date d3 = quant::add_duration( quant::date(2000, 2, 29),
                                                  quant::make_months(1),
                                                  true );
            BOOST_CHECK_EQUAL(d3, quant::date(2000, 3, 31));

            quant::date d4 = quant::add_duration( quant::date(2000, 2, 29),
                                                  quant::make_months(1),
                                                  false );
            BOOST_CHECK_EQUAL(d4, quant::date(2000, 3, 29));

            quant::date d5 = quant::add_duration( quant::date(2000, 2, 28),
                                                  quant::make_months(1),
                                                  true );
            BOOST_CHECK_EQUAL(d5, quant::date(2000, 3, 28));

            quant::date d6 = quant::add_duration( quant::date(2000, 2, 28),
                                                  quant::make_months(1),
                                                  false );
            BOOST_CHECK_EQUAL(d6, quant::date(2000, 3, 28));

            quant::date d7 = quant::add_duration( quant::date(2000, 2, 29),
                                                  quant::make_months(2),
                                                  true );
            BOOST_CHECK_EQUAL(d7, quant::date(2000, 4, 30));

            quant::date d8 = quant::add_duration( quant::date(2000, 2, 29),
                                                  quant::make_months(2),
                                                  false );
            BOOST_CHECK_EQUAL(d8, quant::date(2000, 4, 29));

            quant::date d9 = quant::add_duration( quant::date(2000, 2, 28),
                                                  quant::make_months(2),
                                                  true );
            BOOST_CHECK_EQUAL(d9, quant::date(2000, 4, 28));

            quant::date d10 = quant::add_duration( quant::date(2000, 2, 28),
                                                   quant::make_months(2),
                                                   false );
            BOOST_CHECK_EQUAL(d10, quant::date(2000, 4, 28));

            quant::date d11 = quant::add_duration( quant::date(2000, 2, 29),
                                                   quant::make_years(1),
                                                   true );
            BOOST_CHECK_EQUAL(d11, quant::date(2001, 2, 28));

            quant::date d12 = quant::add_duration( quant::date(2000, 2, 29),
                                                   quant::make_years(1),
                                                   false );
            BOOST_CHECK_EQUAL(d12, quant::date(2001, 2, 28));

            quant::date d13 = quant::add_duration( quant::date(2000, 2, 28),
                                                   quant::make_years(1),
                                                   true );
            BOOST_CHECK_EQUAL(d13, quant::date(2001, 2, 28));

            quant::date d14 = quant::add_duration( quant::date(2000, 2, 28),
                                                   quant::make_years(1),
                                                   false );
            BOOST_CHECK_EQUAL(d14, quant::date(2001, 2, 28));

            quant::date d15 = quant::add_duration( quant::date(1999, 2, 28),
                                                   quant::make_years(1),
                                                   true );
            BOOST_CHECK_EQUAL(d15, quant::date(2000, 2, 29));

            quant::date d16 = quant::add_duration( quant::date(1999, 2, 28),
                                                   quant::make_years(1),
                                                   false );
            BOOST_CHECK_EQUAL(d16, quant::date(2000, 2, 28));
        }

    } // anonymous namespace

    ////////////////////////////////////////////////////////////////////////////////////////////////

    void add_duration_test_cases(boost::unit_test::test_suite& suite) {
        suite.add( BOOST_TEST_CASE(&test_duration_default_ctor) );
        suite.add( BOOST_TEST_CASE(&test_swap_durations) );
        suite.add( BOOST_TEST_CASE(&test_parse_string_to_duration) );
        suite.add( BOOST_TEST_CASE(&test_parse_signed_string_to_duration) );
        suite.add( BOOST_TEST_CASE(&test_parse_invalid_string_to_duration) );
        suite.add( BOOST_TEST_CASE(&test_add_duration) );
    }

} // namespace zzheng::test
} // namespace zzheng


